package ace.module.oauth2.server.core.impl.converter.impl;

import ace.cmp.core.constants.CoreConstant;
import ace.cmp.core.utils.SystemClockUtils;
import ace.module.oauth2.server.core.impl.converter.*;
import ace.module.oauth2.server.core.impl.dao.entity.Oauth2RegisteredClient;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.AllArgsConstructor;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.stereotype.Component;

/**
 * @author caspar
 * @date 2023/10/12 11:45
 */
@AllArgsConstructor
@Component
public class Oauth2RegisteredClientFromRegisteredClientConverterImpl
    implements Oauth2RegisteredClientFromRegisteredClientConverter {
  private final ClientAuthenticationMethodToStringConverter
      clientAuthenticationMethodToStringConverter;
  private final AuthorizationGrantTypeToStringConverter authorizationGrantTypeToStringConverter;
  private final ClientSettingsToJsonConverter clientSettingsToJsonConverter;
  private final TokenSettingsToJsonConverter tokenSettingsToJsonConverter;

  @Override
  public Oauth2RegisteredClient convert(RegisteredClient source) {
    return Optional.ofNullable(source)
        .map(
            s -> {
              Oauth2RegisteredClient d =
                  Oauth2RegisteredClient.builder()
                      .id(s.getId())
                      .clientId(s.getClientId())
                      .clientIdIssuedAt(s.getClientIdIssuedAt().toEpochMilli())
                      .clientSecret(s.getClientSecret())
                      .clientSecretExpiresAt(
                          Optional.ofNullable(s.getClientSecretExpiresAt())
                              .map(Instant::toEpochMilli)
                              .orElse(null))
                      .clientName(s.getClientName())
                      .clientAuthenticationMethods(
                          this.clientAuthenticationMethodToStringConverter.convertToString(
                              s.getClientAuthenticationMethods()))
                      .authorizationGrantTypes(
                          this.authorizationGrantTypeToStringConverter.convertToString(
                              s.getAuthorizationGrantTypes()))
                      .redirectUris(this.convertSetToString(s.getRedirectUris()))
                      .scopes(this.convertSetToString(s.getScopes()))
                      .clientSettings(
                          this.clientSettingsToJsonConverter.convert(s.getClientSettings()))
                      .tokenSettings(
                          this.tokenSettingsToJsonConverter.convert(s.getTokenSettings()))
                      .deleteFlag(CoreConstant.DELETE_FLAG_NOT.toString())
                      .createTime(SystemClockUtils.currentTimeMillis())
                      .updateTime(SystemClockUtils.currentTimeMillis())
                      .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
                      .build();
              return d;
            })
        .orElse(null);
  }

  private String convertSetToString(Set<String> redirectUris) {
    return Stream.ofNullable(redirectUris).flatMap(Set::stream).collect(Collectors.joining(","));
  }
}
